//
//  UILabel+TapAttribute.m
//  MoreCoin
//
//  Created by 林宁宁 on 2019/10/24.
//  Copyright © 2019 MoreCoin. All rights reserved.
//

#import "UILabel+TapAttribute.h"
#import <objc/runtime.h>
#import <CoreText/CoreText.h>
#import "YHDefines.h"
#import "NSMutableAttributedString+YH.h"

//NSString const *LC_TapBlock = @"LC_TapBlock";
//NSString const *LC_TextHelper = @"LC_TextHelper";

//@interface UILabel ()
//
//@property (nonatomic,strong) LCTextHelper *lc_textHelper;
//
//@end

@implementation UILabel (TapAttribute)


- (void)setYh_tapBlock:(void (^)(UILabel * ,NSInteger, NSAttributedString * _Nonnull))yh_tapBlock {
    objc_setAssociatedObject(self, @selector(yh_tapBlock), yh_tapBlock, OBJC_ASSOCIATION_COPY);
    self.userInteractionEnabled = YES;
    for(UIGestureRecognizer * gesture in self.gestureRecognizers){
        if([gesture isKindOfClass:[UITapGestureRecognizer class]] &&
           [gesture.name isEqualToString:NSStringFromClass(self.class)]){
            return;
        }
    }
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(yh_tapAction:)];
    tapGestureRecognizer.name = NSStringFromClass(self.class);
    [self addGestureRecognizer:tapGestureRecognizer];
}
- (void (^)(UILabel * ,NSInteger, NSAttributedString * _Nonnull))yh_tapBlock {
    return objc_getAssociatedObject(self, @selector(yh_tapBlock));
}

#pragma mark -Event
- (void)yh_tapAction:(UITapGestureRecognizer *)recognizer {
    
    CGPoint point = [recognizer locationInView:recognizer.view];
    
//    NSLog(@"location = %@",NSStringFroYHGPoint(location));
    
    [self yh_getTapFrameWithTouchPoint:point];
}

- (void)yh_getTapFrameWithTouchPoint:(CGPoint)point{
    
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.attributedText);
    CGMutablePathRef Path = CGPathCreateMutable();
    CGPathAddRect(Path, NULL, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height + 20));
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), Path, NULL);
    CFArrayRef lines = CTFrameGetLines(frame);
    
    CGFloat total_height = [self.attributedText yh_getSizeConstrainedToSize:CGSizeMake(self.bounds.size.width, FLT_MAX)].height;
    
    if (!lines) {
        CFRelease(frame);
        CFRelease(framesetter);
        CGPathRelease(Path);
        return;
    }
    
    CFIndex count = CFArrayGetCount(lines);
    
    CGPoint origins[count];
    
    CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins);
    
    CGAffineTransform transform = [self yb_transformForCoreText];
    
    for (CFIndex i = 0; i < count; i++) {
        CGPoint linePoint = origins[i];
        
        CTLineRef line = CFArrayGetValueAtIndex(lines, i);
        
        CGRect flippedRect = [self yb_getLineBounds:line point:linePoint];
        
        CGRect rect = CGRectApplyAffineTransform(flippedRect, transform);
        
        CGFloat lineOutSpace = (self.bounds.size.height - total_height) / 2;
        
        rect.origin.y = lineOutSpace + [self yb_getLineOrign:line];
        if(self.textAlignment == NSTextAlignmentCenter){
            rect.origin.x = (CGRectGetWidth(self.frame) - CGRectGetWidth(rect))*0.5;
        }
        else if(self.textAlignment == NSTextAlignmentRight){
            rect.origin.x = CGRectGetWidth(self.frame) - CGRectGetWidth(rect);
        }
//        if (self.enlargeTapArea) {
//            rect.origin.y -= 5;
//            rect.size.height += 10;
//        }
        
        if (CGRectContainsPoint(rect, point)) {
            
            CGPoint relativePoint = CGPointMake(point.x - CGRectGetMinX(rect), point.y - CGRectGetMinY(rect));

            CFIndex index = CTLineGetStringIndexForPosition(line, relativePoint);
            
            CGFloat offset;
            
            CTLineGetOffsetForStringIndex(line, index, &offset);
            
            if (offset > relativePoint.x) {
                index = index - 1;
            }
            
            NSAttributedString * attributedSubstring = [self.attributedText attributedSubstringFromRange:NSMakeRange(index, 1)];
            
            if(self.yh_tapBlock){
                self.yh_tapBlock(self, index, attributedSubstring);
            }
            break;
        }
    }
    CFRelease(frame);
    CFRelease(framesetter);
    CGPathRelease(Path);
}

- (CGAffineTransform)yb_transformForCoreText
{
    return CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f);
}


- (CGRect)yb_getLineBounds:(CTLineRef)line point:(CGPoint)point
{
    CGFloat ascent = 0.0f;
    CGFloat descent = 0.0f;
    CGFloat leading = 0.0f;
    CGFloat width = (CGFloat)CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
    CGFloat height = 0.0f;
    
    CFRange range = CTLineGetStringRange(line);
    NSAttributedString * attributedString = [self.attributedText attributedSubstringFromRange:NSMakeRange(range.location, range.length)];
    if ([attributedString.string hasSuffix:@"\n"] && attributedString.string.length > 1) {
        attributedString = [attributedString attributedSubstringFromRange:NSMakeRange(0, attributedString.length - 1)];
    }
    height = [attributedString yh_getSizeConstrainedToSize:CGSizeMake(self.bounds.size.width, MAXFLOAT)].height;
    return CGRectMake(point.x, point.y , width, height);
}


- (CGFloat)yb_getLineOrign:(CTLineRef)line
{
    CFRange range = CTLineGetStringRange(line);
    if (range.location == 0) {
        return 0.;
    }else {
        NSAttributedString * attributedString = [self.attributedText attributedSubstringFromRange:NSMakeRange(0, range.location)];
        if ([attributedString.string hasSuffix:@"\n"] && attributedString.string.length > 1) {
            attributedString = [attributedString attributedSubstringFromRange:NSMakeRange(0, attributedString.length - 1)];
        }
        return [attributedString yh_getSizeConstrainedToSize:CGSizeMake(self.bounds.size.width, FLT_MAX)].height;
    }
}

@end


//
//
//@interface LCTextHelper ()
//
//@property (nonatomic,strong)NSTextStorage *textStorage;
//@property (nonatomic,strong)NSLayoutManager *layoutManager;
//@property (nonatomic,strong)NSTextContainer *textContainer;
//
//@end
//
//@implementation LCTextHelper
//
//- (instancetype)init {
//    self = [super init];
//    if (self) {
//        self.textStorage = [NSTextStorage new];
//        self.layoutManager = [NSLayoutManager new];
//        self.textContainer = [NSTextContainer new];
//        [self.textStorage addLayoutManager:self.layoutManager];
//        [self.layoutManager addTextContainer:self.textContainer];
//    }
//    return self;
//}
//- (void)selectLocation:(CGPoint)location OfLabel:(UILabel *)label selectedBlock:(void (^)(NSInteger, NSAttributedString *))selectedBlock {
//    self.textContainer.size = label.bounds.size;
//    self.textContainer.lineFragmentPadding = 0;
//    self.textContainer.maximumNumberOfLines = label.numberOfLines;
//    self.textContainer.lineBreakMode = label.lineBreakMode;
//
////    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:label.attributedText];
////    NSRange textRange = NSMakeRange(0, attributedText.length);
////    [attributedText addAttribute:NSFontAttributeName value:label.font range:textRange];
////    NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
////    paragraphStyle.alignment = label.textAlignment;
////    [attributedText addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:textRange];
//    [self.textStorage setAttributedString:label.attributedText.mutableCopy];
//
//    CGSize textSize = [self.layoutManager usedRectForTextContainer:self.textContainer].size;
//    //    location.x -= (CGRectGetWidth(self.label.frame) - textSize.width) / 2;
//    location.y -= (CGRectGetHeight(label.frame) - textSize.height) / 2;
//
//    NSUInteger glyphIndex = [self.layoutManager glyphIndexForPoint:location inTextContainer:self.textContainer];
//    CGFloat fontPointSize = label.font.pointSize;
//    [self.layoutManager setAttachmentSize:CGSizeMake(fontPointSize, fontPointSize) forGlyphRange:NSMakeRange(label.text.length - 1, 1)];
//    NSAttributedString *attributedSubstring = [label.attributedText attributedSubstringFromRange:NSMakeRange(glyphIndex, 1)];
//    CGRect glyphRect = [self.layoutManager boundingRectForGlyphRange:NSMakeRange(glyphIndex, 1)
//                                                                inTextContainer:self.textContainer];
////    if (!CGRectContainsPoint(glyphRect, location)) {
////        if (CGRectContainsPoint(CGRectMake(0, 0, textSize.width, textSize.height), location)) {
//////            NSLog(@"in");
////        }
////        selectedBlock(-1,nil);
////        return;
////    }
//    selectedBlock(glyphIndex,attributedSubstring);
//}
//
//@end
